package br.uece.comp.paa.util;

import java.math.BigDecimal;

import br.uece.comp.paa.entity.param.Solucao;

public class GeradorCombinacao {

	private int p;

	private int[] atual;

	private final int INICIAL;

	private final int FINAL;

	private boolean gerado;

	public GeradorCombinacao(int n, int p, int inicial) {
		this.p = p;
		INICIAL = inicial;
		FINAL = n - 1 + INICIAL;

		atual = new int[p];

		for (int i = 0; i < p; i++) {
			atual[i] = INICIAL + i;
		}

		gerado = true;
	}

	public GeradorCombinacao(int n, int p) {
		this(n, p, 0);
	}

	public Solucao proxima() {
		Solucao solucao = new Solucao(p);

		if (!gerado) {

			for (int k = atual.length - 1; k >= 0; k--) {

				if (atual[k] < FINAL - (atual.length - k - 1)) {
					atual[k]++;

					for (int h = k + 1; h < atual.length; h++) {
						atual[h] = atual[h - 1] + 1;
					}

					break;
				}
			}
		}
		// Forma a solução.
		for (int i = 0; i < atual.length; i++) {
			solucao.setNextAresta(atual[i]);
		}
		gerado = false;
		return solucao;
	}

	public void setProxima(int indice) {

		for (int i = indice; i >= 0; i--) {

			if (atual[i] < FINAL - (atual.length - i - 1)) {

				atual[i]++;
				for (int h = i + 1; h < atual.length; h++) {
					atual[h] = atual[h - 1] + 1;
				}
				gerado = true;
				break;
			}
		}
	}

	public boolean temProxima() {

		if (gerado) {
			return true;
		} else {
			for (int i = atual.length - 1; i >= 0; i--) {
				if (atual[i] != FINAL - (atual.length - 1 - i)) {
					return true;
				}
			}

			return false;
		}
	}

	public static BigDecimal qtdCombinacoes(int n, int p) {
		System.out.println("n: " + n + " | p: " + p);
		return (fat(n).divide(fat(p).multiply(fat(n - p))));
	}

	public static BigDecimal fat(int n) {
		BigDecimal result = new BigDecimal(1);
		for (int i = n; i > 0; i--) {
			result = result.multiply(new BigDecimal(i));
		}

		return result;
	}

	/**
	 * Pequeno teste do gerador de números.
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		final int N = 6;
		final int P = 3;

		GeradorCombinacao gc = new GeradorCombinacao(N, P);

		double total = qtdCombinacoes(N, P).doubleValue();

		int count = 0;

		while (gc.temProxima()) {
			count++;
			System.out.println(gc.proxima());
			gc.setProxima(2);
		}
//
//		System.out.println(gc.proxima());
//		System.out.println(gc.proxima());
//		gc.setProxima(1);
//		System.out.println(gc.proxima());
//		System.out.println(gc.proxima());
//		gc.setProxima(0);
//		System.out.println(gc.proxima());
//		System.out.println(gc.proxima());
//		gc.setProxima(0);
//		System.out.println(gc.proxima());
//		gc.setProxima(1);
//		System.out.println(gc.proxima());
//
//		System.out.println(gc.temProxima());
//
		System.out.println(count);
		System.out.println(total);

	}
}
